package com.amigo.online.provider.merchant.service.impl;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.amigo.online.common.base.service.BaseService;
import com.amigo.online.common.core.response.StatusCode;
import com.amigo.online.common.param.RedisKey;
import com.amigo.online.common.param.dto.merchant.GoodsCommentDto;
import com.amigo.online.common.param.dto.merchant.MerchantCommentDto;
import com.amigo.online.common.param.result.UserInfo;
import com.amigo.online.common.param.result.merchant.GoodsCommentInfo;
import com.amigo.online.common.param.result.merchant.MerchantCommentInfo;
import com.amigo.online.provider.merchant.common.GlobalController;
import com.amigo.online.provider.merchant.common.RwRedisService;
import com.amigo.online.provider.merchant.exception.GoodsException;
import com.amigo.online.provider.merchant.mapper.GoodsCommentImgMapper;
import com.amigo.online.provider.merchant.mapper.GoodsCommentMapper;
import com.amigo.online.provider.merchant.mapper.GoodsMapper;
import com.amigo.online.provider.merchant.mapper.MerchantMapper;
import com.amigo.online.provider.merchant.model.entity.GoodsComment;
import com.amigo.online.provider.merchant.model.entity.GoodsCommentImg;
import com.amigo.online.provider.merchant.service.GoodsCommentImgService;
import com.amigo.online.provider.merchant.service.GoodsCommentService;
import com.amigo.online.provider.merchant.utils.ConvertUtil;

/**
 * <code>GoodsCommentServiceImpl.java</code>
 * <p>
 *
 * </p>
 * <p>
 *
 * @author LuChen
 * @version 1.0
 * @company Amigo
 * @time 2018年12月15日 下午5:10:52
 * @lastUpdate 无
 * </p>
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class GoodsCommentServiceImpl extends BaseService<GoodsComment> implements GoodsCommentService {

    @Autowired
    private MerchantMapper merchantMapper;

    @Autowired
    private GoodsCommentMapper goodsCommentMapper;

    @Autowired
    private GoodsCommentImgMapper goodsCommentImgMapper;

    @Autowired
    private GoodsCommentImgService goodsCommentImgService;

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private RwRedisService redisService;


    @Override
    public boolean commentGoodById(GoodsCommentDto dto) {
        UserInfo user = GlobalController.getNowUser();
        Long userId = user.getId();
        GoodsComment gc = new GoodsComment();
        //不能评论自己的商品
        if (goodsMapper.checkGoodsIsUserHas(dto.getGoodsId(), userId) > 0) {
            throw new GoodsException(StatusCode.CANNOT_COMMENT_YOUROWN_GOODS);
        }
        //不能重复评论
        if (goodsMapper.checkGoodsIsCommented(dto.getGoodsId(), userId) > 0) {
            throw new GoodsException(StatusCode.ALREADY_COMMENT);
        }
        gc.setUserId(userId);
        gc.setContent(dto.getContent());
        gc.setStar(dto.getStar());
        gc.setCreatedTime(System.currentTimeMillis() / 1000);
        gc.setDeleted(0);
        gc.setGoodsId(dto.getGoodsId());
        if (goodsCommentMapper.insertUseGeneratedKeys(gc) > 0) {
            Long id = gc.getId();
            if (id > 0 && goodsCommentImgService.insertCommentImg(id, dto.getList())) {
                //添加成功后计算新的商品好评率  向下取整
                List<Integer> list = goodsCommentMapper.getNewFeedbackByGoodsId(dto.getGoodsId());
                double sum = list.get(0);
                double good = list.get(1);
                Integer newfeedback = null;
                if (sum != 0) {
                    newfeedback = (int) (good / sum * 100);
                }
                //将该店铺的评分总数和评论人数更新redis并返回新的评分
                Double grade = getNewGrade(dto.getMerchantId(), dto.getStar());
                //更新数据库不管返回是不是1  都返回成功
                goodsMapper.updateFeedbackById(dto.getGoodsId(), newfeedback);
                merchantMapper.updateGradeById(dto.getMerchantId(), grade);
                return true;
            }
        } else {
            logger.info("数据异常");
        }
        return true;
    }

    @Override
    public boolean deletecommentById(Long id) {
        GoodsComment mc = new GoodsComment();
        mc.setId(id);
        mc = goodsCommentMapper.selectOne(mc);
        Long goodsId = mc.getGoodsId();
        mc.setDeleted(1);
        mc.setDeletedTime(System.currentTimeMillis() / 1000);
        if (goodsCommentMapper.updateByPrimaryKey(mc) > 0) {
            //删除成功后计算好评率
            List<Integer> list = goodsCommentMapper.getNewFeedbackByGoodsId(goodsId);
            double sum = list.get(0);
            double good = list.get(1);
            Integer newfeedback = null;
            if (sum != 0) {
                newfeedback = (int) (good / sum * 100);
            }
            if (goodsMapper.updateFeedbackById(goodsId, newfeedback) > 0) {
                return true;
            }
            ;
        } else {
            logger.info("数据异常");
        }
        return true;
    }

    @Override
    public GoodsCommentInfo getCommentGoodsList(Integer id, Integer type, Integer status, Integer page, Integer size) {
        page = GlobalController.checkPage(page, size);
        List<Integer> countList = goodsCommentMapper.getCommentCountByGoodId(id);
        List<GoodsComment> list = goodsCommentMapper.getCommentInfoByGoodId(id, type, status, (page - 1) * size, size);
        List<Long> imgIds = new ArrayList<>();
        if (list.size() > 0) {
            imgIds = list.stream()
                    .map(GoodsComment::getId)
                    .collect(Collectors.toList());
        }
        List<GoodsCommentImg> imgList = new ArrayList<>();
        if (imgIds.size() > 0) {
            imgList = goodsCommentImgMapper.getImgsByCommentId(imgIds);
        }
        List<MerchantCommentInfo> infos = ConvertUtil.goodsCommentToCommentInfo2(list, imgList);
        GoodsCommentInfo info = new GoodsCommentInfo(infos, countList);
        return info;
    }


    @Override
    public List<MerchantCommentInfo> getCommentMerList(MerchantCommentDto dto) {
        Integer page = GlobalController.checkPage(dto.getPage(), dto.getSize());
        Integer size = dto.getSize();
        dto.setPage(page);
        List<GoodsComment> list = goodsCommentMapper.getMerCommentListByMerId(dto.getMerchantId(), (page - 1) * size,
                size, dto.getStatus(), dto.getType());
        List<Long> idList = list.stream().map(GoodsComment::getId).collect(Collectors.toList());
        List<GoodsCommentImg> imgList = new ArrayList<>();
        if (idList.size() > 0) {
            imgList = goodsCommentImgMapper.getImgsByCommentId(idList);
        }
        List<MerchantCommentInfo> info = ConvertUtil.goodsCommentToCommentInfo3(list, imgList);
        return info;
    }

    @Override
    public List<MerchantCommentInfo> getCommentMerList(Integer page, Integer size) {
        UserInfo user = GlobalController.getNowUser();
        page = GlobalController.checkPage(page, size);
        Long userId = user.getId();
        List<GoodsComment> list = goodsCommentMapper.getMerchantCommentList(userId, (page - 1) * size, size);
        List<Long> idList = list.stream().map(GoodsComment::getId).collect(Collectors.toList());
        List<GoodsCommentImg> imgList = new ArrayList<>();
        if (idList.size() > 0) {
            imgList = goodsCommentImgMapper.getImgsByCommentId(idList);
        }
        List<MerchantCommentInfo> info = ConvertUtil.goodsCommentToCommentInfo(list, user, imgList);
        return info;
    }

    @SuppressWarnings("unchecked")
    private Double getNewGrade(Long merchantId, Integer star) {
        DecimalFormat df = new DecimalFormat("#.0");
        List<Integer> gradeInfo = redisService.opsForListRead().range(RedisKey.MERCHANT_COMMENT_KEY + merchantId, 0, -1);
        double grade;
        if (gradeInfo == null || gradeInfo.size() < 2) {
            gradeInfo = new ArrayList<>(2);
            gradeInfo.add(star);
            gradeInfo.add(1);
            redisService.delete(RedisKey.MERCHANT_COMMENT_KEY + merchantId);
            redisService.opsForList().leftPushAll(RedisKey.MERCHANT_COMMENT_KEY + merchantId, gradeInfo);
            grade = (double) star / 1 * 2;
        } else {
            Integer sumCommentPeopleCount = gradeInfo.get(0) + 1;
            Integer sumStar = star + gradeInfo.get(1);
            gradeInfo.set(0, sumStar);
            gradeInfo.set(1, sumCommentPeopleCount);
            redisService.delete(RedisKey.MERCHANT_COMMENT_KEY + merchantId);
            redisService.opsForList().leftPushAll(RedisKey.MERCHANT_COMMENT_KEY + merchantId, gradeInfo);
            grade = (double) sumStar / (double) sumCommentPeopleCount * 2;
        }
        if (grade >= 10) {
            grade = 10.0;
        }
        return Double.valueOf(df.format(grade));
    }

}
